package dan.frontend
import chisel3._
import chisel3.util._
import dan.common.CoreBundle
import dan.common.Consts.CFI_BITS
import dan.common.ITLBExp
import dan.common.UOp
import dan.common.HasCoreParam
import dan.frontend
import javax.xml.crypto.dsig.spec.RSAPSSParameterSpec
import dan.backend.PredecodeSignals

class FetchBufDeq extends CoreBundle{
    // 每周期发射 coreWidth 条微指令到后端
    val uops = Vec(coreWidth, Valid(new UOp()))
}

class FetchPack extends CoreBundle{
    val fetchWidth = frontendParam.fetchWidth
    val fetchBytes = frontendParam.fetchBytes
    val ftqSize = frontendParam.ftqSize
    val pc = UInt(vaBits.W)
    val instrPack = Vec(fetchWidth, Bits(instrBits.W))

    val cfiIdx = Valid(UInt(log2Ceil(fetchWidth).W))
    val cfiType = UInt(CFI_BITS.W)
    val cfiIsCall = Bool()
    val cfiIsRet = Bool()
    val targetBits = frontendParam.targetBits
    val rasTopEntry = UInt(targetBits.W)
    val ftqIdx = UInt(log2Ceil(ftqSize).W)
    val mask = UInt(fetchWidth.W)
    val brMask = UInt(fetchWidth.W)
    val rasPtr = new RASIdx()
    val exp = Valid(new ITLBExp())
    val bpuMeta = Vec(fetchWidth, new BPUMeta())
}

class F3Pack extends CoreBundle {
    // parameters
    val fetchWidth = frontendParam.fetchWidth

    val pc         = UInt(vaBits.W)
    val instrs     = Vec(fetchWidth, UInt(instrBits.W))
    val mask       = UInt(fetchWidth.W)
    val exception  = Valid(new ITLBExp)
    val rasPtr     = new RASIdx
    val predecode  = Vec(fetchWidth, new PredecodeSignals)
}

trait HasFTQParam extends HasCoreParam{
    val ftqSize = frontendParam.ftqSize
    val rasSize = frontendParam.rasSize
    val fetchWidth = frontendParam.fetchWidth
    val fetchBytes = frontendParam.fetchBytes
    val targetBits = frontendParam.targetBits
    val idxBits = log2Ceil(ftqSize)
}

class FTQPack extends CoreBundle with HasFTQParam{
    val cfiIdx = Valid(UInt(log2Ceil(fetchWidth).W))
    val cfiTaken = Bool()
    val cfiMispredict = Bool()
    val cfiType = UInt(CFI_BITS.W)
    val brMask = UInt(fetchWidth.W)
    val cfiIsCall = Bool()
    val cfiIsRet = Bool()
    val rasTopEntry = UInt(targetBits.W)
    val rasIdx = UInt(log2Ceil(rasSize).W)
}

class FTQIdx2PC extends CoreBundle with HasFTQParam{
    val idx = Input(UInt(idxBits.W))
    val entry = Output(new FTQPack())
    val rasPtr = Output(new RASIdx())
    val pc = Output(UInt(vaBits.W))
    val commitPC = Output(UInt(vaBits.W))
    val nextPC = Output(UInt(vaBits.W))
    val nextPCValid = Output(Bool())
}

